package spring.security.core.lock;

import org.springframework.util.Assert;

import spring.security.core.lock.annotation.SyncLock;
import spring.security.core.support.SpringContextSupport;

public class LockUtils {

	private static RedisLockHandler lockHandler = (RedisLockHandler) SpringContextSupport
			.getBean(RedisLockHandler.class);

	public static void lock(String key) {
		lock(key, (Boolean) null, (Long) null, (Long) null);
	}

	public static void lock(String key, Boolean failfast) {
		lock(key, failfast, (Long) null, (Long) null);
	}

	public static void lock(String key, Boolean failfast, Long timeout, Long obtainTimeout) {
		Assert.hasText(key, "加锁内容不能为空");
		SyncLock syncLock = (SyncLock) lockHandler.getThreadLocal().get();
		if (syncLock == null) {
			throw new IllegalArgumentException("同步锁参数错误,请在方法上增加@SyncLock注解");
		} else {
			SyncLockConf conf = new SyncLockConf(syncLock);
			if (failfast != null) {
				conf.setFailfast(failfast.booleanValue());
			}

			if (timeout != null) {
				conf.setTimeout(timeout.longValue());
			}

			if (timeout != null) {
				conf.setObtainTimeout(obtainTimeout.longValue());
			}

			String namespace = lockHandler.getNamespace();
			String lockKey = getLockKey(namespace, syncLock.key(), key);
			lockHandler.lock(conf, lockKey);
		}
	}

	public static void unlock(String key) {
		Assert.hasText(key, "释放锁内容不能为空");
		SyncLock syncLock = (SyncLock) lockHandler.getThreadLocal().get();
		if (syncLock == null) {
			throw new IllegalArgumentException("同步锁参数错误,请在方法上增加@SyncLock注解");
		} else {
			String namespace = lockHandler.getNamespace();
			String lockKey = getLockKey(namespace, syncLock.key(), key);
			lockHandler.releaseSubLock(syncLock.key(), lockKey);
		}
	}

	private static String getLockKey(String namespace, String key, String lock) {
		String lockKeyStr = namespace + ":" + key + ":sub:" + lock;
		return lockKeyStr;
	}

	static {
		if (lockHandler == null) {
			throw new IllegalStateException("请在spring配置文件中定义RedisLockHandler");
		}
	}
	
}
